"""The application's model objects"""
import sqlalchemy as sa
from sqlalchemy import orm
from sqlalchemy.orm import relationship, backref
from sqlalchemy import MetaData

from hashlib import md5

from cpswarehouse.model import meta

#def init_model(engine):
#    """Call me before using any of the tables or classes in the model"""
#
#    meta.Session.configure(bind=engine)
#    meta.engine = engine

#Dimensions:

#could use something much smaller than int to store this
year_dimension = sa.Table("year_dimension", meta.metadata,
    sa.Column("year", sa.types.Integer, primary_key=True), 
    )

grade_dimension = sa.Table("grade_dimension", meta.metadata,
    #figure out what things like "80" and "9x" are...then coerce into int?
    sa.Column("grade", sa.types.String(255), primary_key=True), 
    )

race_dimension = sa.Table("race_dimension", meta.metadata,
    sa.Column("id", sa.types.String(32), primary_key=True), #change to hex number
    sa.Column("nativeamerican", sa.types.Integer, default=0), 
    sa.Column("asian", sa.types.Integer, default=0), 
    sa.Column("black", sa.types.Integer, default=0), 
    sa.Column("hispanic", sa.types.Integer, default=0), 
    sa.Column("multiracial", sa.types.Integer, default=0), 
    sa.Column("white", sa.types.Integer, default=0), 
    sa.Column("total", sa.types.Integer, default=0), 
    )

school_dimension = sa.Table("school_dimension", meta.metadata,
    sa.Column("id", sa.types.String(36), primary_key=True),
    sa.Column("school", sa.types.String(255)), #nullable=False),
    sa.Column("unit", sa.types.Integer),
    sa.Column("address", sa.types.String(255)), 
    sa.Column("latitude", sa.types.Float),
    sa.Column("longitude", sa.types.Float),
    )

#Facts:

record_fact = sa.Table("record_fact", meta.metadata,
    sa.Column("id", sa.types.Integer, primary_key=True),
    sa.Column("year_id", sa.ForeignKey("year_dimension.year")),
    sa.Column("grade_id", sa.ForeignKey("grade_dimension.grade")),
    sa.Column("race_id", sa.ForeignKey("race_dimension.id")), 
    sa.Column("school_id", sa.ForeignKey("school_dimension.id")),
    )

#suitable for one time load _only_
class UniqueOnly(object):
    
    @classmethod
    def get_instance(cls, *args, **kwargs):
        instance = cls(*args, **kwargs)

        if cls.items.has_key(instance.get_primary_key()):
            return cls.items[instance.get_primary_key()]
        else:
            cls.items[instance.get_primary_key()] = instance
            return instance

    def get_primary_key():
        pass

    #this doesn't work in the superclass
    #__str__ = __unicode__


class YearDimension(UniqueOnly):
    items = dict()

    def __init__(self, year):
        self.year = year

    def get_primary_key(self):
        return self.year

    def __unicode__(self):
        return u"%s" % self.year


class GradeDimension(UniqueOnly):
    items = dict()

    def __init__(self, grade):
        self.grade = grade

    def get_primary_key(self):
        return self.grade

    def __unicode__(self):
        return u"%s" % self.grade



class RaceDimension(UniqueOnly):
    items = dict()

    def __init__(self, 
                 nativeamerican=0, 
                 asian=0,
                 black=0,
                 hispanic=0,
                 multiracial=0,
                 white=0,
                 ):

        key_hash = md5()
        self.total = 0
        
        self.nativeamerican = nativeamerican
        key_hash.update(nativeamerican)
        self.total+=int(nativeamerican)

        self.asian = asian
        key_hash.update(asian)
        self.total+=int(asian)

        self.black = black
        key_hash.update(black)
        self.total+=int(black)

        self.hispanic = hispanic
        key_hash.update(hispanic)
        self.total+=int(hispanic)

        self.multiracial = multiracial
        key_hash.update(multiracial)
        self.total+=int(multiracial)

        self.white = white
        key_hash.update(white)
        self.total+=int(white)

        key_hash.update('%s' % self.total)
        self.id = key_hash.hexdigest()

    def get_primary_key(self):
        return self.id

    def __unicode__(self):
        return u"%s: %s" % (self.race, self.count)


class SchoolDimension(UniqueOnly):
    items = dict()

    def __init__(self, school, unit):
        self.school = school
        self.unit = unit

        key_hash = md5()
        key_hash.update(school)
        self.id = key_hash.hexdigest()
        

    def get_primary_key(self):
        return self.school

    def __unicode__(self):
        return u"%s" % self.school

class RecordFact(object):

    #year = relationship(YearDimension, backref='facts')
    #grade = relationship(GradeDimension, backref='facts')
    #race = relationship(RaceDimension, backref='facts')
    #school = relationship(SchoolDimension, backref='facts')
    
    def __init__(self, year, grade, race, school):
        self.year_id = year.year
        self.grade_id = grade.grade
        self.race_id = race.id
        self.school_id = school.id


    def __unicode__(self):
        return u"%s: %s" % (self.year_id, self.grade_id)


orm.mapper(YearDimension, year_dimension)
orm.mapper(GradeDimension, grade_dimension)
orm.mapper(RaceDimension, race_dimension)
orm.mapper(SchoolDimension, school_dimension, )
orm.mapper(RecordFact, record_fact, 
           properties={'school':relationship(SchoolDimension, backref='facts'),
                       'year':relationship(YearDimension, backref='facts'),
                       'grade':relationship(GradeDimension, backref='facts'),
                       })
